import {GLView} from 'expo-gl';
import {Renderer} from 'expo-three';
import * as React from 'react';
import {Text} from 'react-native';
import {
    AmbientLight,
    Mesh,
    PerspectiveCamera,
    PointLight,
    Scene,
    SpotLight,
    SphereBufferGeometry,
    MeshPhongMaterial,
    Group,
} from 'three';

export default function App() {
    React.useEffect(() => {
        return () => clearTimeout(timeout);
    }, []);

    let camera, scene, renderer, stats, gui;
    let geometry;
    const amount = 5; //手机中没有window
    const count = Math.pow(amount, 3);
    const group = new Group();
    let lastTime1 = 0, lastTime2 = 0, lastTime5 = 0; //for every 1s, 2s, 5s
    let lastFrame1 = 0, lastFrame2 = 0, lastFrame5 = 0;
    let fps1 = 0, fps2 = 0, fps5 = 0;
    let frame = 0;
    let triangleCount = 0, vertexCount = 0;
    const [fps, setFps] = React.useState('');


    return (
        <React.Fragment>
            <GLView
                style={{flex: 1}}
                onContextCreate={async (gl) => {
                    const {drawingBufferWidth: width, drawingBufferHeight: height} = gl;
                    const sceneColor = 0x6ad6f0;

                    // Create a WebGLRenderer without a DOM element
                    renderer = new Renderer({gl, antialias: true});
                    renderer.setSize(width, height);
                    renderer.setClearColor(sceneColor);

                    camera = new PerspectiveCamera(70, width / height, 0.01, 1000);
                    camera.position.set(0, 0, amount * 2);
                    camera.lookAt(0, 0, 0);

                    scene = new Scene();

                    const ambientLight = new AmbientLight(0x101010);
                    scene.add(ambientLight);

                    const pointLight = new PointLight(0xffffff, 2, 1000, 1);
                    pointLight.position.set(0, 200, 200);
                    scene.add(pointLight);

                    const spotLight = new SpotLight(0xffffff, 0.5);
                    spotLight.position.set(0, 500, 100);
                    spotLight.lookAt(scene.position);
                    scene.add(spotLight);

                    const segments = 128;
                    geometry = new SphereBufferGeometry(0.4, segments, segments);
                    const material = new MeshPhongMaterial({color: 0x00ff00});
                    if (group) {
                        let offset = -(amount - 1) / 2;
                        for (let x = 0; x < amount; x++) {
                            for (let y = 0; y < amount; y++) {
                                for (let z = 0; z < amount; z++) {
                                    const newMesh = new Mesh(geometry, material);
                                    newMesh.position.set(offset + x, offset + y, offset + z);
                                    group.add(newMesh)
                                }
                            }
                        }
                    }
                    scene.add(group);

                    triangleCount = geometry.index.count / 3 * count;
                    console.log('triangleCount:', triangleCount);
                    vertexCount = geometry.attributes.position.count * count;
                    console.log('vertexCount:', vertexCount);

                    // Setup an animation loop
                    const render = () => {
                        requestAnimationFrame(render);
                        frame++;

                        let time = Date.now();
                        let deltaFrame, deltaTime;
                        if (lastTime1 !== 0) {
                            if (time - lastTime1 > 1000) {
                                deltaFrame = frame - lastFrame1;
                                deltaTime = time - lastTime1;
                                fps1 = Math.round(deltaFrame / deltaTime * 1000);
                                lastFrame1 = frame;
                                lastTime1 = time;
                            }
                        } else {
                            lastTime1 = time;
                            lastFrame1 = frame;
                        }

                        if (lastTime2 !== 0) {
                            if (time - lastTime2 > 2000) {
                                deltaFrame = frame - lastFrame2;
                                deltaTime = time - lastTime2;
                                fps2 = Math.round(deltaFrame / deltaTime * 1000);
                                lastFrame2 = frame;
                                lastTime2 = time;
                            }
                        } else {
                            lastTime2 = time;
                            lastFrame2 = frame;
                        }

                        if (lastTime5 !== 0) {
                            if (time - lastTime5 > 5000) {
                                deltaFrame = frame - lastFrame5;
                                deltaTime = time - lastTime5;
                                fps5 = Math.round(deltaFrame / deltaTime * 1000);
                                lastFrame5 = frame;
                                lastTime5 = time;
                            }
                        } else {
                            lastTime5 = time;
                            lastFrame5 = frame;
                        }

                        //update the fps information
                        setFps(`${fps1}(1s) ${fps2}(2s) ${fps5}(5s) T:${triangleCount} V:${vertexCount}`);

                        time = time * 0.001;

                        group.rotation.x = Math.sin(time / 4);
                        group.rotation.y = Math.sin(time / 2);

                        renderer.render(scene, camera);
                        gl.endFrameEXP();
                    };
                    render();
                }}
            />
            <Text style={{position: 'absolute', bottom: 5, left: 5, fontSize: 18}}>{fps}</Text>
        </React.Fragment>
    );
}